﻿using Autofac.Extensions.DependencyInjection;
using EntityFrameWorkCore;
using FrameWorkCore.CustomFilter.Dto;
using FrameWorkCore.EFCore;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using ShardingCore.Sharding;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FrameWorkCore
{
    
    public class CustomActionFilter : ActionFilterAttribute
    {


        private readonly IEnumerable<AbstractShardingDbContext> dbContexts;
        private readonly IServiceProvider serviceProvider;


        public CustomActionFilter(IServiceProvider _serviceProvider) 
        {
            serviceProvider = _serviceProvider;
            dbContexts = ((AutofacServiceProvider)_serviceProvider).LifetimeScope.ComponentRegistry.Registrations
            .Where(x => typeof(AbstractShardingDbContext).IsAssignableFrom(x.Activator.LimitType))
            .Select(x => (AbstractShardingDbContext)serviceProvider.GetService(x.Activator.LimitType));
        }


        public override void  OnActionExecuting(ActionExecutingContext context)
        {
            
            if (!context.ModelState.IsValid)//Do not use the system default calibration using aop for unity check dynamic webapi and controller
            {
                //context.ModelState.ValidationState
                var errors = context.ModelState
                    .Where(e => e.Value.Errors.Count > 0)
                    .Select(e => e.Value.Errors.First().ErrorMessage)
                    .ToList();

                var str = string.Join(" | ", errors);
                context.HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
                context.Result = new JsonResult(new ResultDto
                {
                    Code = StatusCodes.Status400BadRequest,
                    Msg = str
                });
            }
            else
                foreach (var dbContext in dbContexts)
                    dbContext.Database.BeginTransaction();


        }

        public override  void OnActionExecuted(ActionExecutedContext context)
        {
           if (context.ModelState.IsValid)
           try
           {
               if (context.Exception is not null)
                      throw new UserFriendlyException(context.Exception.Message);//Method in the catch exceptions thrown exception to aop


               foreach (var dbContext in dbContexts)
               {
                   if (dbContext.Database.CurrentTransaction != null)
                       dbContext.SaveChanges(); //This could throw exceptions
               }
           
               foreach (var dbContext in dbContexts)
               {
                   if (dbContext.Database.CurrentTransaction != null)
                       dbContext.Database.CommitTransaction();//To prevent the savechanges didn't really commit an error here
               }
                  
               if ( context.Result is ObjectResult objRes)
                    context.Result = new JsonResult(new ResultDto
                    { 
                        Code = StatusCodes.Status200OK,
                        Msg = "Success",
                        Data = objRes.Value
                    });
               else if (context.Result is EmptyResult)
                    context.Result = new JsonResult(new ResultDto
                    {
                        Code = StatusCodes.Status200OK,
                        Msg = "Success",
                    });

           }
           catch
           {
                    
               throw; //If it is the action of aop saved to the database abnormal abnormal optimization hint sorry happened during processing requests a server internal abnormal!
           }
        }
    }


  
}
